/**
 *
 */
package com.ctrip.cap.internal.appium.suite.android;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.TreeSet;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.ISuite;
import org.testng.ISuiteListener;

import com.ctrip.cap.common.exception.CapException;
import com.ctrip.cap.common.shell.ShellCommand;
import com.ctrip.cap.device.android.AndroidDevice;
import com.ctrip.cap.device.android.impl.DefaultAndroidApp;
import com.ctrip.cap.device.android.impl.DefaultDeviceStore;
import com.ctrip.cap.device.model.AppInfo;
import com.ctrip.cap.device.model.DeviceInfo;
import com.ctrip.cap.internal.appium.suite.Preprocess;
import com.ctrip.cap.internal.performance.Profilers;
import com.ctrip.cap.internal.suite.ReporterSuiteListener;
import com.ctrip.cap.internal.suite.SuiteManListener;
import com.ctrip.cap.internal.suite.SuiteUtility;
import com.ctrip.cap.internal.util.HttpUtils;
import com.ctrip.cap.lanucher.AppiumConfig;
import com.ctrip.cap.lanucher.Environment;

/**
 * @author zwxu
 */
public class AndroidStartupListener implements ISuiteListener {

    public static final Logger logger = LoggerFactory
            .getLogger(AndroidStartupListener.class);

    // private static String REPORT_URL =
    // "http://autotest.sh.ctriptravel.com/Pages/Reports/CILogReport.aspx?JobID=";
    @Override
    public void onStart(ISuite suite) {

        AppiumConfig config = (AppiumConfig) suite
                .getAttribute(SuiteManListener.CAP_CONFIG);

        clearWorkspace();

        preparePackage(config, suite);

        tempWorkroundForGetApkString(config);

        collectDeviceAndApp(suite, config);

        Preprocess preprocess = null;
        switch (config.getDriverType()) {
            case ChromeDriver:
                preprocess = new H5Preprocess();
                break;
            case Selendroid:
                preprocess = new AppPreprocess(config);
                break;
            case UIAutomator:
                preprocess = new AppPreprocess(config);
                break;
            default:
                break;

        }
        Profilers.preAppium().start("preprocess");

        if (preprocess != null) {
            if (Environment.isLab()) {
                preprocess.process();
            } else {
                if (config.isFullReset()) {
                    preprocess.process();
                }
            }

        }
        suite.setAttribute(SuiteManListener.CAP_CONFIG, config);
        logger.info("preprocess finished");
    }

    private void tempWorkroundForGetApkString(AppiumConfig config) {
        try {
            String appPath = config.getApp();
            if (StringUtils.isNotEmpty(appPath)) {
                String stringsJsonPath = Environment.capHome()
                        .getAbsolutePath();
                String apkToolsPathString = "\""
                        + System.getProperty("user.home")
                        + "\\AppData\\Roaming\\npm\\node_modules\\appium\\node_modules\\appium-adb\\jars\\appium_apk_tools.jar\"";

                CommandLine commandLine = new CommandLine("java");
                commandLine.addArguments(new String[]{"-jar",
                        apkToolsPathString, "stringsFromApk", appPath,
                        stringsJsonPath});

                ShellCommand.exec(commandLine);
            }
        } catch (Exception e) {
        }
    }

    private void collectDeviceAndApp(ISuite suite, AppiumConfig config) {

        if (!config.getDriverType().isH5()) {
            String app = config.getApp();
            DefaultAndroidApp dapp = new DefaultAndroidApp(new File(app));
            AppInfo appInfo = dapp.toAppInfo();

            suite.setAttribute(ReporterSuiteListener.APP_INFO, appInfo);
        }

        TreeSet<AndroidDevice> devices = (TreeSet<AndroidDevice>) DefaultDeviceStore
                .getInstance().getDevices();
        AndroidDevice device = devices.first();

        DeviceInfo deviceInfo = device.getDeviceInfo();

        suite.setAttribute(ReporterSuiteListener.DEVICE_INFO, deviceInfo);

    }

    private void overriteAppiumAppConfig(AppiumConfig config, ISuite suite) {

        if (Environment.isLab()) {
            String app = Environment.getAppPath();
            if (StringUtils.isNotBlank(app)) {
                config.setApp(app);
                SuiteUtility.updateParameter(suite, "app", app);
            }
        }

        String app = config.getApp();
        if (StringUtils.isNotBlank(app) && app.toLowerCase().startsWith("http")) {
            app = HttpUtils.downloadApp(app);
        }
        config.setApp(app);
        config.setAppFileName(FilenameUtils.getName(app));

    }

    private void preparePackage(AppiumConfig appiumConfig, ISuite suite) {

        if (appiumConfig.getDriverType().isH5()) {
            return;
        }
        overriteAppiumAppConfig(appiumConfig, suite);
        String app = appiumConfig.getApp();
        appiumConfig.setAppFileName(FilenameUtils.getName(app));
        File appPath = new File(app);

        for (AndroidDevice device : DefaultDeviceStore.getInstance()
                .getDevices()) {
            File appFile = SuiteUtility.constructFileName(
                    device.getSerialNumber(), app);
            logger.info("try copy uat app for device src {} to dest {}",
                    appPath, appFile);
            try {
                FileUtils.copyFile(appPath, appFile);
            } catch (IOException e) {
                throw new CapException("file copy", e);
            }
        }

    }

    @Override
    public void onFinish(ISuite suite) {
    }

    private void clearWorkspace() {

        Environment.clearWorkspace();

        File tempDir = Environment.getTempDirectory();
        File[] selendroidFiles = tempDir.listFiles(new SelendroidFileFilter());
        for (File file : selendroidFiles) {
            try {
                FileUtils.forceDelete(file);
            } catch (IOException e) {
                logger.warn("clearWorkspace");
            }
        }
    }

    public static class SelendroidFileFilter implements FilenameFilter {

        @Override
        public boolean accept(File dir, String name) {
            return name.toLowerCase().contains("selendroid");
        }

    }
}
